import time

import win32con
import win32gui
from selenium.common.exceptions import NoSuchElementException

from config.config import SeleniumConfig


def presence_of_element_located(driver, by, value):
    """
    判断元素是否存在
    :param driver: 浏览器
    :param by: 查找方式
    :param value: 值
    :return: 元素是否存在
    """
    driver.implicitly_wait(0)
    try:
        return driver.find_element(by, value)
    except NoSuchElementException:
        return None
    finally:
        driver.implicitly_wait(SeleniumConfig.timeout)


def choice_element(elements, text, HTML=False):
    """
    选择元素
    :param elements: 元素列表
    :param text: 文本
    :return: 元素
    """
    for element in elements:
        if not HTML:  # 不比较/默认比较text
            if element and element.text.find(text) != -1:
                return element
        else:
            if element and element.get_attribute('outerHTML').find(text) != -1:
                return element
    return None


def upload_file(directory, file_path, waitTime=1):
    """
    上传文件,用win32操纵windows控件
    :param directory: 文件夹路径
    :param file_path: 文件路径
    :param waitTime: 等待时间
    """
    print(directory, file_path)
    dialog = win32gui.FindWindow('#32770', '打开')  # 对话框
    # 判断dialog是否存在
    if dialog == 0: return False
    ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, 'ComboBoxEx32', None)
    comboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, 'ComboBox', None)
    edit = win32gui.FindWindowEx(comboBox, 0, 'Edit', None)
    button = win32gui.FindWindowEx(dialog, 0, 'Button', None)  # 打开按钮

    win32gui.SendMessage(edit, win32con.WM_SETTEXT, None, directory)  # 切换目录路径
    time.sleep(waitTime)
    win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button)  # 点击打开按钮
    time.sleep(waitTime)
    win32gui.SendMessage(edit, win32con.WM_SETTEXT, None, file_path)  # 发送文件路径
    time.sleep(waitTime)
    win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button)  # 点击打开按钮
    return True


def retry(class_):
    """
    重试
    :param class_: 调用类
    :return: 回调操作
    """

    def callback(operation, check, args=None):
        """
        回调操作
        :param operation: 操作
        :param check: 检查操作是否成功
        :param args: 操作参数
        :return: 是否成功操作
        """

        args = args if args is not None else []
        for attempt in range(SeleniumConfig.attempts):
            try:
                # 执行操作
                operation(*args)
                # 检查操作是否成功
                if check(*args): return True
                # 等待结果
                time.sleep(SeleniumConfig.attemptWaitTime)
                # 重试
                if check(*args): return True
            except Exception as e:
                print(e)
                time.sleep(SeleniumConfig.attemptWaitTime)
            print(f"尝试{class_.__name__}中的{operation.__name__}次数 :{attempt + 1}/{SeleniumConfig.attempts}")
        print("达到最大重试次数，操作失败。")
        # 抛出异常，告诉是哪个操作失败
        raise Exception(f"操作失败：{class_.__name__}中的{operation.__name__}")

    return callback
